package com.example.httplibrary.download;

import android.content.Context;
import android.util.Log;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Streaming;
import retrofit2.http.Url;

/**
 * Author: 李巷阳
 * Date: 2020/9/4
 * Part:
 * Description:
 */
public class DownLoadManagerToos {
    private static final String TAG = "DownLoadToos";
    private static DownLoadManagerToos sIsntance;
    private OkHttpClient okHttpClient;
    private static final int DEFAULT_TIMEOUT = 10;
    private DownloadApi apiService;
    private boolean isStop=false;

    public void setStop(boolean stop) {
        isStop = stop;
    }

    public static DownLoadManagerToos getInstance() {
        if (sIsntance == null) {
            synchronized (DownLoadManagerToos.class) {
                if (sIsntance == null) {
                    sIsntance = new DownLoadManagerToos();
                }
            }
        }
        return sIsntance;
    }


    private DownLoadManagerToos() {
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl("https://github.com/")
                .build();
        apiService = retrofit.create(DownloadApi.class);
    }

    public void downloadFile(final Context mContext, final long range, final String download_url, final String download_file_Name, final String download_local_path, final DownLoadCallBack downloadCallback) {
        //断点续传时请求的总长度
        File file = new File(download_local_path, download_file_Name);
        String totalLength = "-";
        if (file.exists()) {
            totalLength += file.length();
        }

        apiService.executeDownload("bytes=" + Long.toString(range) + totalLength, download_url)
                .subscribe(new Observer<ResponseBody>() {


                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseBody responseBody) {
                        RandomAccessFile randomAccessFile = null;
                        InputStream inputStream = null;
                        long load_current_range = range;
                        long responseLength = 0;
                        try {
                            byte[] buf = new byte[2048];
                            int len = 0;
                            responseLength = responseBody.contentLength();
                            inputStream = responseBody.byteStream();
                            String filePath = download_local_path;
                            File file = new File(filePath, download_file_Name);
                            File dir = new File(filePath);
                            if (!dir.exists()) {
                                dir.mkdirs();
                            }
                            randomAccessFile = new RandomAccessFile(file, "rwd");
                            if (range == 0) {
                                randomAccessFile.setLength(responseLength);
                            }
                            randomAccessFile.seek(range);

                            int progress = 0;
                            int lastProgress = 0;

                            while ((len = inputStream.read(buf)) != -1) {
                                // 如果用户暂停 ,就调用暂停的回调
                                if(isStop)
                                {
                                    break;
                                }
                                randomAccessFile.write(buf, 0, len);
                                load_current_range += len;
                                lastProgress = progress;
                                progress = (int) (load_current_range * 100 / randomAccessFile.length());
                                if (progress > 0 && progress != lastProgress) {
                                    downloadCallback.onProgress(progress);
                                }
                            }
                            // 如果用户不是暂停,走到这里,则返回下载成功
                            if(!isStop)
                            {
                                downloadCallback.onCompleted();
                            }
                        } catch (Exception e) {
                            Log.d(TAG, e.getMessage());
                            downloadCallback.onError(e.getMessage());
                            e.printStackTrace();
                        } finally {
                            try {
                                DownLoadSPUtils.save(mContext,download_url, load_current_range);

                                if (randomAccessFile != null) {
                                    randomAccessFile.close();
                                }

                                if (inputStream != null) {
                                    inputStream.close();
                                }
                                if(isStop){
                                    downloadCallback.onStop();
                                }
                                isStop=false;
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                        }
                    }



                    @Override
                    public void onError(Throwable e) {
                        downloadCallback.onError(e.toString());
                    }

                    @Override
                    public void onComplete() {

                    }


                });
    }

    public interface DownloadApi {
        @Streaming
        @GET
        Observable<ResponseBody> executeDownload(@Header("Range") String range, @Url() String url);
    }
}
